package com.joymart.compute.service;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.joymart.common.model.Range;
import com.joymart.order.model.Order;
import com.joymart.user.model.CachedUser;
import com.joymart.user.service.UserCacheManager;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Service
public class ReconciliationService {

    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
    @Autowired
    private UserCacheManager userCacheManager;


    public Object computeReconciliation(String userId, Range range) {
        String selfSql = """
                select 
                       second_seller_id,
                       count(*)        as       order_count,
                       sum(total_price) as  total_amount,
                       sum(total_pv) as       sales_pv,
                       sum(first_seller_profit) sales_profit,
                       sum(second_seller_profit) as scecond_profit
                from "order"
                where status = :status
                and first_seller_id = :userId
                and created_at between :start and :end
                group by second_seller_id
                """;

        List<SelfPart> selfParts = namedParameterJdbcTemplate.query(selfSql, Map.of(
                "userId", userId, "start", range.getStart(), "end", range.getEnd(), "status", Order.Status.RECEIVED.name()
        ), new BeanPropertyRowMapper<>(SelfPart.class));

        String secSql = """
                select 
                       second_seller_id,
                       count(*)        as       order_count,
                       sum(total_price) as  total_amount,
                       sum(total_pv) as       sales_pv,
                       sum(first_seller_profit) first_profit,
                       sum(second_seller_profit) sales_profit
                from "order"
                where status = :status
                and second_seller_id = :userId
                and created_at between :start and :end
                group by second_seller_id
                """;
        List<MngPart> mngParts = namedParameterJdbcTemplate.query(secSql, Map.of(
                "userId", userId, "start", range.getStart(), "end", range.getEnd(), "status", Order.Status.RECEIVED.name()
        ), new BeanPropertyRowMapper<>(MngPart.class));

        String branchesSql = """
                select 
                       first_seller_id,
                       count(*)        as       order_count,
                       sum(total_price) as  total_amount,
                       sum(first_seller_profit) as first_seller_profit
                from "order"
                where status = :status
                and second_seller_id = :userId
                and created_at between :start and :end
                group by first_seller_id
                """;

        List<BranchesPart> branchesParts = namedParameterJdbcTemplate.query(branchesSql, Map.of(
                "userId", userId, "start", range.getStart(), "end", range.getEnd(), "status", Order.Status.RECEIVED.name()
        ), new BeanPropertyRowMapper<>(BranchesPart.class));

        selfParts.forEach(selfPart -> selfPart.setSecondSeller(userCacheManager.get(selfPart.getSecondSellerId())));
        mngParts.forEach(mngPart-> mngPart.setSecondSeller(userCacheManager.get(mngPart.getSecondSellerId())));
        branchesParts.forEach(branchesPart -> branchesPart.setFirstSeller(userCacheManager.get(branchesPart.getFirstSellerId())));
        return new Reconciliation(selfParts, branchesParts, mngParts);

    }

    @Data
    @AllArgsConstructor
    private static class Reconciliation {
        private List<SelfPart> selfParts;
        private List<BranchesPart> branchesParts;
        private List<MngPart> mngParts;
    }

    @Data
    private static class SelfPart {

        @JsonIgnore
        private String secondSellerId;

        private CachedUser secondSeller;

        /*
         *  单数
         */
        private BigDecimal orderCount;
        /*
         * 销售PV
         */
        private BigDecimal salesPv;
        /**
         * 自营利润
         */
        private BigDecimal salesProfit;

        private BigDecimal scecondProfit;


        /**
         * 订单总金额
         */
        private BigDecimal totalAmount;


        public BigDecimal getOrderCount() {
            return Optional.ofNullable(orderCount).orElse(BigDecimal.ZERO);
        }
        public BigDecimal getScecondProfit(){
            return Optional.ofNullable(scecondProfit).orElse(BigDecimal.ZERO);
        }

        public BigDecimal getSalesPv() {
            return Optional.ofNullable(salesPv).orElse(BigDecimal.ZERO);
        }

        public BigDecimal getSalesProfit() {
            return Optional.ofNullable(salesProfit).orElse(BigDecimal.ZERO);
        }

        public BigDecimal getTotalAmount() {
            return Optional.ofNullable(totalAmount).orElse(BigDecimal.ZERO);
        }

        /**
         * 上交金额
         *
         * @return
         */
        public BigDecimal getHandOutMoney() {
            return this.getTotalAmount().subtract(this.getSalesProfit(), MathContext.DECIMAL64);
        }

    }


    @Data
    private static class MngPart {

        @JsonIgnore
        private String secondSellerId;

        private CachedUser secondSeller;

        /**
         * 育成利润
         */
        private BigDecimal firstProfit;

        /**
         * 育成利润
         */
        private BigDecimal salesProfit;


        /**
         * 订单总金额
         */
        private BigDecimal totalAmount;

        public BigDecimal getSalesProfit() {
            return Optional.ofNullable(salesProfit).orElse(BigDecimal.ZERO);
        }
        public  BigDecimal getFirstProfit(){
            return Optional.ofNullable(firstProfit).orElse(BigDecimal.ZERO);
        }


        public BigDecimal getTotalAmount() {
            return Optional.ofNullable(totalAmount).orElse(BigDecimal.ZERO);
        }

        public BigDecimal getHeadQuarterPrice() {
            return this.getTotalAmount().subtract(this.getSalesProfit(), MathContext.DECIMAL64).subtract(this.getFirstProfit(), MathContext.DECIMAL64);
        }

    }

    @Data
    private static class BranchesPart {

        @JsonIgnore
        private String firstSellerId;

        private CachedUser firstSeller;

        /*
         *  单数
         */
        private BigDecimal orderCount;

        /**
         * 订单总金额
         */
        private BigDecimal totalAmount;

        private BigDecimal firstSellerProfit;

        public BigDecimal getOrderCount() {
            return Optional.ofNullable(orderCount).orElse(BigDecimal.ZERO);
        }

        public BigDecimal getTotalAmount() {
            return Optional.ofNullable(totalAmount).orElse(BigDecimal.ZERO);
        }

        public BigDecimal getFirstSellerProfit() {
            return Optional.ofNullable(firstSellerProfit).orElse(BigDecimal.ZERO);
        }

        /**
         * 上交金额
         *
         * @return
         */
        public BigDecimal getHandInMoney() {
            return this.getTotalAmount().subtract(this.getFirstSellerProfit(), MathContext.DECIMAL64);
        }
    }

}
